iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0

上一篇我們直接設定庫的導出目錄(LIBRARY_OUTPUT_PATH)到上一層的 lib 資料夾中讓主程式使用,但是實際使用上通常會使用 "install()" 指令來設定安裝規則,將庫和標頭檔安裝到指定路徑或系統目錄上,而且有了安裝規則就可以依此來解除安裝,不用手動去安裝路徑刪除檔案。

CMake 語法

install

定義:生成安裝規則

  • 安裝標頭檔

install(FILES <files_name> DESTINATION )

files_name : 標頭檔或檔案名稱
dir : 將要安裝的路徑

  • 安裝庫

install(TARGETS <targets_name> DESTINATION )

targets_name : 庫名稱
dir : 將要安裝的路徑

GNUInstallDirs

定義:GNU 的標準安裝路徑
定義出的變量
${CMAKE_INSTALL_PREFIX} : /usr/local
${CMAKE_INSTALL_BINDIR} : /bin
${CMAKE_INSTALL_INCLUDEDIR} : /include

範例1 : 在內部安裝

$ git clone https://github.com/m11112089/2023_iT_CMake.git
$ cd ~/2023_iT_CMake/Day14/範例1在內部安裝

1. 編輯 MathFunctions/CMakeLists.txt
在 MathFunctions/CMakeLists.txt 中設定庫和標頭檔的安裝路徑

install(TARGETS mysqrt DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/../Main/lib)
# 安裝庫到 ~/2023_iT_CMake/Day14/範例1在內部安裝/Main/lib
install(FILES include/mysqrt.h DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/../Main/include)
# 安裝頭文件到 ~/2023_iT_CMake/Day14/範例1在內部安裝/Main/include

2. 進入/MathFunctions/build 資料夾編譯出動態庫文件

$ cd /MathFunctions/build
$ cmake ..
$ make

3. 安裝
因為make只能產生目標文件與安裝規則,所以需要再使用make install將目標文件依照安裝規則安裝至指定位置。

$ make install

執行完指令後可以看到確切的安裝位置訊息。

kai@esoc:~/2023_iT_CMake/Day14/範例1在內部安裝/MathFunctions/build$ make install
[100%] Built target mysqrt
Install the project...
-- Install configuration: ""
-- Up-to-date: /home/kai/2023_iT_CMake/Day14/範例1在內部安裝/MathFunctions/../Main/lib/libmysqrt.so.1.0.0
-- Up-to-date: /home/kai/2023_iT_CMake/Day14/範例1在內部安裝/MathFunctions/../Main/lib/libmysqrt.so.1
-- Up-to-date: /home/kai/2023_iT_CMake/Day14/範例1在內部安裝/MathFunctions/../Main/lib/libmysqrt.so
-- Up-to-date: /home/kai/2023_iT_CMake/Day14/範例1在內部安裝/MathFunctions/../Main/include/mysqrt.h

4. 查看生成出來的檔案

kai@esoc:~/2023_iT_CMake/Day14/範例1在內部安裝/Main$ tree
.
├── build
├── CMakeLists.txt
├── include
│   └── mysqrt.h
├── lib
│   ├── libmysqrt.so -> libmysqrt.so.1
│   ├── libmysqrt.so.1 -> libmysqrt.so.1.0.0
│   └── libmysqrt.so.1.0.0
└── src
    └── main.cpp

5. 編譯與執行主專案

$ cd ~/2023_iT_CMake/Day14/範例1在內部安裝/Main/build
$ cmake ..
$ make
$ ./main 100

範例2 : 安裝至系統路徑

$ cd ~/2023_iT_CMake/Day14/範例2安裝至系統路徑

系統路徑簡介

根據GNU Coding Standards的規則,使用者通常將標頭檔安裝在/usr/local/include,庫會安裝在/usr/local/bin。

範例

1. 編輯 MathFunctions/CMakeLists.txt
在CMakeLists.txt中設定安裝庫和頭文件的系統路徑,先將GNUInstallDirs引入,再設定安裝路徑。

include(GNUInstallDirs)
# 引入 GNUInstallDirs 變數
install(FILES include/mysqrt.h DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) 
# 安裝庫到 /usr/local/include
install(TARGETS mysqrt DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}) 
# 安裝頭文件到 /usr/local/bin

2. 進入/MathFunctions/build 資料夾編譯出動態庫文件

$ cd /MathFunctions/build
$ cmake ..
$ make

3. 安裝
因為是系統路徑,所以需要超級使用者(superuser)權限

$ sudo make install

kai@esoc:~/2023_iT_CMake/Day14/範例2安裝至系統路徑/MathFunctions/build$ sudo make install
[sudo] password for kai: 
[100%] Built target mysqrt
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/include/mysqrt.h
-- Installing: /usr/local/bin/libmysqrt.so.1.0.0
-- Up-to-date: /usr/local/bin/libmysqrt.so.1
-- Up-to-date: /usr/local/bin/libmysqrt.so

4. 查看生成出來的檔案
在完成編譯與安裝指令後,可以看到在/usr/local/bin和/usr/local/include會出現主程式所需要的標頭檔與動態庫

kai@esoc:/usr/local/bin$ tree
.
├── docker-compose -> /usr/lib/docker/cli-plugins/docker-compose
├── libmysqrt.so -> libmysqrt.so.1
├── libmysqrt.so.1 -> libmysqrt.so.1.0.0
├── libmysqrt.so.1.0.0

kai@esoc:/usr/local/include$ tree -L 1
.
├── librealsense2
├── librealsense2-gl
└── mysqrt.h

5. 編輯 CMakeLists.txt

include(GNUInstallDirs)
# 引入 GNUInstallDirs 變數
include_directories(${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})
# 設定include路徑
target_link_directories(main PUBLIC ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR})
# 設定執行檔main搜尋lib的路徑
target_link_libraries(main mysqrt)
# 將mysqrt連結到執行檔main

6. 編譯與執行主專案

$ cd build
$ cmake ..
$ make
$ ./main 100

7. 再使用ldd指令查看庫鍊結情況

$ ldd main

kai@esoc:~/2023_iT_CMake/Day14/範例2安裝至系統路徑/Main/build$ ldd main 
	linux-vdso.so.1 (0x00007ffd713f8000)
	libmysqrt.so.1 => /usr/local/bin/libmysqrt.so.1 (0x00007f951d281000)
	libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f951d000000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f951d23b000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f951cc00000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f951cf19000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f951d28e000)

可以發現主程式順利鍊結到系統路徑中的mysqrt動態庫

Reference

Program Library HOWTO
ld.so(8) — Linux manual page
GNU Coding Standards


上一篇
[Day 13] 實際操作動態庫的版本號
下一篇
[Day 15] 解除安裝庫
系列文
建構屬於自己的C/C++專案 : 我的30天CMake學習之旅29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言